# 2024.06.21——比特Python自习笔记
# 列表与元组

# 列表——一种让程序员在代码中批量表示/保存数据的方式，列表中的数据可以修改
# 元组——与列表相似也是一种让程序员在代码中批量表示/保存数据的方式，元组中的数据不能修改
# 列表和元组可以理解为C/C++中的数组，通过一个变量来表示多个数据
# 列表和元组大部分的功能都是差不多的，但是列表可变，元组不可变
num = [1, 2, 3, 4, 5, 6]
print(num)
num[0] = 7
print(num)
num = (1, 2, 3, 4, 5, 6)
print(num)
# num[0] = 5  # 'tuple' object does not support item assignment
# print(num)

# 列表的创建
# 1.直接通过字面常量来创建
num = []
print(type(num))
# 2.使用list()来创建
num = list()
print(type(num))
# 3.在创建列表时在[]中指定初始值，元素之间用，来分割
num = [1, 2, 3, 4, 5, 6]
print(num)
# 4.与C/C++/JAVA中的数组不同的是，列表中可以放置不同类型的元素
num = [1, 2, 'abd', 4, 5.6, 6]
print(num)
# 5.列表中的元素可以通过下标访问的方式来获取列表中的元素
# 下标访问操作符[]
print(num[0])
# 与数组一样，通过[]来访问列表中的元素时，需要在[]中填入需要访问元素的下标/索引
# 列表中的元素下标/索引与数组一样，都是从0开始计数
# 6.当我们需要修改列表中的元素时，同样可以通过下标来修改列表中的元素
num[3] = '1234'
print(num)
# 7.与数组一样，列表下标的有效范围也是从0~len-1或者是-len~-1，
# 当访问索引值超过len或小于-len的元素时则会出现越界
# print(num[6])   # list index out of range
print(num[-6])
# print(num[-7])  # list index out of range
# 8.通过内建函数len()可以计算列表中的元素个数
print(len(num))
# 9.Python中的下标可以写成负数
# 如num[-1]对应的元素实际上时num[len - 1]
print(num[-1])
print(num[len(num) - 1])

# 切片操作
# 以此取出一组连续的元素，相当于得到一个子列表
# 通过[:]来完成对列表的切片操作
# 1.在[:]中放入列表中需要进行切片的起始索引和结束索引，对应的区间为前闭后开区间
print(num[1:3])     # 输出元素：2， ’abd'
# 2.使用切片时可以省略边界
print(num[2:])  # 省略后边界，从起始索引开始，一直取到整个列表结束
print(num[:2])  # 省略前边界，从0号索引开始，一直取到结束索引的前一个元素
print(num[:])   # 省略前后边界，从0号索引开始，一直取到整个列表结束
# 切片中的索引还可以是负数，负数索引的起始点为列表中的最后一个元素，起始索引为-1
print(num[:-1])
# 切片操作是一个比较高效的操作，进行切片的时候，只是取出了原有列表的一个部分，并不涉及到"数据的拷贝"
# 3.切片操作还可以指定步长进行切片
print(num[::2])     # 第一个冒号是在进行切片，第二个冒号是在以指定步长进行切片，2表示步长为2
# 4.步长的数值还可以是负数——当步长为负数时表示从后往前取
print(num[::-2])
# 5.当切片中的范围超出有效下标之后，不会出现异常，而是尽可能的把复合要求的元素获取到
print(num[1:100:2])

# 列表元素的遍历
# 遍历——把一组数据中的每个元素都依次取出来，并进行某种操作
# 遍历可以通过循环来实现
# 1.通过循环将列表中的元素依次存储在变量中完成遍历
num = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for elem in num:
    print(elem, end=' ')    # 此时可以打印元素，但无法修改列表中的元素
    elem = 0
    print(elem)
print(num)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 2.通过下标依次访问列表中的元素
for i in range(0, len(num)):
    print(num[i], end=' ')   # 此时既可以打印元素，又可以修改列表中的元素
    num[i] = 0
    print(num[i])
print(num)  # [0, 0, 0, 0, 0, 0, 0, 0, 0]

# 插入操作
# 1.通过append()向列表末尾插入一个元素
num = [1, 2, 3]
num.append(4)
print(num)
# 此处的append是搭配列表对象num来一起使用的函数，而不是作为一个独立的函数
# 这种要搭配对象来使用的函数也叫做方法
# 在Python中，对象就可以被视为'变量'
# 2.通过insert()在列表任意位置插入一个元素
num.insert(6, 5)
print(num)
# 通过insert进行插入时，第一个参数为插入的下标，第二个参数为插入的元素
# 当插入下标大于当前列表的最大下标时，则直接将新元素插入到列表末尾

# 查找和删除
# 查找
# 1.使用in来查找列表中是否存在某个元素
num = [1, 2, 3, 4, 5]
print(0 in num)
print(0 not in num)
# 查找的返回值为布尔类型，存在返回True，不存在返回False
# 2.使用index方法来判定需要查找元素的位置，并得到其在列表中的下标
print(num.index(1))
# print(num.index(0))     # 0 is not in list

# 删除
# 1.使用pop删除列表中的最末尾的元素
print(num)  # [1, 2, 3, 4, 5]
num.pop()
print(num)  # [1, 2, 3, 4]
# 2. 使用pop来删除任意位置的元素
num.pop(0)  # 通过在pop中传入要删除元素的下标来实现需要删除的指定元素
print(num)  # [2, 3, 4]
# 3.使用remove方法来按值删除
num.remove(3)
print(num)  # [2, 4]

# 连接列表
# 1.通过+连接两个列表
num1 = [1, 2, 3]
num2 = [4, 5, 6]
num3 = num1 + num2
print(num1 + num2)
print(num1)
print(num2)
print(num3)
# 通过+拼接获取的列表是一个新的列表，不会改变原列表中的内容
# 2.使用extend进行凭借
# 将后一个列表的内容拼接到前一个列表中
num3 = num1.extend(num2)
print(num1)
print(num2)
print(num3)     # None——extend是无返回值的方法，因此num3获取的是None
# 3.使用+=来进行拼接
num1 = [1, 2, 3]
print(num1)
num1 += num2
print(num1)
print(num2)
# 相比于extend，通过+=操作拼接列表效率更低

# 元组的操作
# 1.创建元组
num1 = ()
print(type(num1))
num2 = tuple()
print(type(num2))
# 2. 创建元组时，也可以指定初始值
num1 = (1, 2, 3)
print(num1)
num2 = tuple(num)
print(num2)
# 3.元组中的元素也可以是任意类型
num1 = (1, 2, 3, 'abc')
print(num1)
# 4.通过下标来获取元组中的元素
print(num1[0])
print(num1[-1])
# print(num1[4])  # 当下标不在有效下标的范围内时同样会报错
# 5.通过切片来获取元组中的一个部分
print(num1[::2])
# 6.可以通过循环来遍历元素
for elem in num1:
    print(elem)
# 7.可以通过in和index来查找元素
print(1 in num1)
print(num1.index(1))
# 8.可以使用+来拼接两个元组
num3 = num1 + num2
print(num3)
# 在列表中所有的读取操作在元组中是同样适用
# 在列表中对列表进行修改的操作在元组中不能使用
# num1.append(4)
# print(num1)     # 'tuple' object has no attribute 'append'
# 9.当进行多元赋值的时候，其本质上是按照元组的方式进行工作的


def func():
    x = 1
    y = 2
    return x, y


X, Y = func()
print(type(func()))     # <class 'tuple'>

# 元组的应用场景
# 在协同开发的过程中，为了防止在传参的过程中参数内容被修改，此时就可以通过元组来避免参数内容被修改
# 不可变对象，是可以哈希的

